package com.sebscape.sebcms.persistence.action;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.sebscape.sebcms.Constants;
import com.sebscape.sebcms.persistence.dao.GenericDao;
import com.sebscape.sebcms.tools.Utils;

public class PersistedObjectActions<T> extends ActionSupport {

	private static final long serialVersionUID = 1L;
	private static Log log = LogFactory.getLog(PersistedObjectActions.class);
    
	private Object persistedObject;
	@SuppressWarnings("unchecked")
	private Class persistedClass;
	
	// the following should be set in the struts-config action params.
	private String classname;
	private String defaultSort = "name";
	private String defaultOrder = "ascending";
	private String listUrl;
	private String editUrl;
	private String saveUrl;
	private String deleteUrl;
	
	public PersistedObjectActions() {
		super();
		log.debug("constructor called.");
	}

	public void setConfirm( String confirmPassword ){
		// TODO: not implemented.
	}
	
	/**
	 * @param classname will be passed in struts-xxx.xml
	 */
	public void setClassname(String classname) {
		log.debug("setClassname( " + classname + " ) called.");
		try {
			this.classname = classname;
			persistedClass = Class.forName(classname);
			persistedObject = persistedClass.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * @param defaultSort the defaultSort to set
	 */
	public void setDefaultSort(String defaultSort) {
		this.defaultSort = defaultSort;
	}

	/**
	 * @param defaultOrder the defaultOrder to set
	 */
	public void setDefaultOrder(String defaultOrder) {
		this.defaultOrder = defaultOrder;
	}
	
	/**
	 * A Url for record-list funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @return the listUrl
	 */
	public String getListUrl() {
		return listUrl;
	}

	/**
	 * A Url for record-list funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @param listUrl the listUrl to be set in the struts-config.xml
	 */
	public void setListUrl(String listUrl) {
		this.listUrl = listUrl;
	}

	/**
	 * A Url for record-edit funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @return the editUrl
	 */
	public String getEditUrl() {
		return editUrl;
	}

	/**
	 * A Url for record-edit funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @param editUrl the editUrl to be set in the struts-config.xml
	 */
	public void setEditUrl(String editUrl) {
		this.editUrl = editUrl;
	}

	/**
	 * A Url for record-save funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @return the saveUrl
	 */
	public String getSaveUrl() {
		return saveUrl;
	}
	
	/**
	 * A Url for record-save funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @param saveUrl the saveUrl to be set in the struts-config.xml
	 */
	public void setSaveUrl(String saveUrl) {
		this.saveUrl = saveUrl;
	}
	
	/**
	 * A Url for record-delete funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @return the deleteUrl
	 */
	public String getDeleteUrl() {
		return deleteUrl;
	}

	/**
	 * A Url for record-delete funcitons to be passed through to the jsp's for navigation within 
	 * this PersistentObject type.
	 * @param deleteUrl the deleteUrl to be set in the struts-config.xml
	 */
	public void setDeleteUrl(String deleteUrl) {
		this.deleteUrl = deleteUrl;
	}
	
	public String getPersistedClassname(){
		return this.getPersistedClass().getSimpleName();
	}
	/////////////////////////////////////////////////////////
	// list/view actions
    ////////////////////////////////////////////////////////

	/**
	 * @return the persistedObject
	 */
	public Object getPersistedObject() {
		return persistedObject;
	}

	/**
	 * @param persistedObject the persistedObject to set
	 */
	@SuppressWarnings("unchecked")
	public void setPersistedObject(Object persistedObject) {
		this.persistedObject = (Class<T>) persistedObject;
	}

	/**
	 * @return the persistedClass
	 */
	@SuppressWarnings("unchecked")
	public Class getPersistedClass() {
		return persistedClass;
	}

	/**
	 * @param persistedClass the persistedClass to set
	 */
	@SuppressWarnings("unchecked")
	public void setPersistedClass(Class persistedClass) {
		this.persistedClass = persistedClass;
	}

	/**
	 * @return the classname
	 */
	public String getClassname() {
		return classname;
	}

	/**
	 * This method is called when we are creating a new instance of an
	 * Object. It loads an empty example of the class which will then be
	 * available to the edit form to display edit fields, etc.
	 */
	public String newForm(){
		ServletActionContext.getRequest().setAttribute(Constants.ATTRIB_OBJECT, this.persistedObject );
		return SUCCESS;
	}
	
	/**
	 * Get a paged List of objects currently stored in the Persistence Service.
	 * params used(optional) in the Request:
	 *   Constants.PARAM_LIST_OFFSET
	 *   Constants.PARAM_LIST_LIMIT
	 *   Constants.PARAM_SORT_COLUMN
	 *   Constants.PARAM_SORT_ORDER
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public String list(){
        Integer offset = Integer.valueOf( Utils.getRequestValue( ServletActionContext.getRequest(),
                Constants.PARAM_LIST_OFFSET, "-1" ) );
        Integer limit = Integer.valueOf( Utils.getRequestValue( ServletActionContext.getRequest(),
                Constants.PARAM_LIST_LIMIT, "-1" ) );
        HttpServletRequest request = ServletActionContext.getRequest();
		String sortColumn = Utils.getRequestValue(request,
                Constants.PARAM_SORT_COLUMN, defaultSort );
        String sortOrder = Utils.getRequestValue(request,
        		Constants.PARAM_SORT_ORDER, defaultOrder );
		log.debug("sortColumn = " + sortColumn);

		GenericDao<Object, Long> dao = new GenericDao<Object, Long>( persistedClass );
		List<Object> list = dao.findAllPaged(sortColumn + " " + sortOrder, offset, limit );
		log.debug( "PersistedObjectActions.list: loaded " + persistedClass.toString() + 
				" list " + (list != null? "size: " + list.size() : "is null" ) );
		request.setAttribute( Constants.ATTRIB_ANY_LIST, list );
		return SUCCESS;
	}

    /**
     * Load instance of the PersistentObject.
     * requires to be in Request:
     *   Constants.PARAM_ID
     * @return
     */
	@SuppressWarnings("unchecked")
	public String load(){
        String id = Utils.getRequestValue( ServletActionContext.getRequest(),
                                Constants.PARAM_ID, null );
        GenericDao dao = new GenericDao( persistedClass );
        try {
            Object o = dao.load( Long.valueOf( id ) );
            ServletActionContext.getRequest().setAttribute(Constants.ATTRIB_OBJECT, o );
            log.debug("load completed; returning SUCCESS.");
            return SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ERROR;
    }

    /**
     * Save the persistedObject
     * @return
     */
	@SuppressWarnings("unchecked")
	public String save(){
    	if( persistedObject != null ){
	    	GenericDao dao = new GenericDao( persistedClass );
	    	try {
	    		log.debug("action will attempt to save class: " + persistedObject.getClass() );
	    		Object newObj = dao.save( persistedObject );
	    		ServletActionContext.getRequest().setAttribute(Constants.ATTRIB_USER, newObj );
	    		log.debug("save user completed; returning SUCCESS.");
	    		return SUCCESS;
	    	} catch (Exception e) {
	    		e.printStackTrace();
	    	}
	    	return ERROR;
    	}
    	return "RETRY";
    }
    
    /**
     * Update the persistedObject in the database. REQUIRES that the PersistedObject implement 
     * the interface IUpdateable.
     * @return
     */
	@SuppressWarnings("unchecked")
	public String update(){
    	// get the id.
        GenericDao dao = new GenericDao( persistedClass );
		try {
			Object o = dao.update( getPersistedObject() );
			ServletActionContext.getRequest().setAttribute(Constants.ATTRIB_OBJECT, o );
			log.debug("load completed; returning SUCCESS.");
			return SUCCESS;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ERROR;
    	// load the object.
    	// update the values.
    	// updates are automatically persisted if they were made while the session was still open.
    }

}
